package com.magenta.maxoptra.routing;


import com.magenta.maxoptra.gis.*;
import com.magenta.maxoptra.routing.geo_routing.*;
import com.magenta.maxoptra.gis.commons.Pair;

import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.Local;
import javax.ejb.Stateless;
import javax.jms.*;

/*
* Project: MaxOptRA v1.2
* User: Ivan Usalko
* Date: 13.09.2009 22:51:48
*
* Copyright (c) 1999-2009 Magenta Corporation Ltd. All Rights Reserved.
* Magenta Technology proprietary and confidential.
* Use is subject to license terms.
*/
@Stateless(name = SampleGeoInfoProvider.JNDI_NAME, description = "TSS geo-info provider interface, supported async and sync queries.")
@Local(GeoInfoProvider.class)
public class SampleGeoInfoProvider extends AbstractGeoInfoProvider {

    public static final String JNDI_NAME = "GeoInfoProviderEJB";
    public static final String DOMAIN = "test";

    @EJB
    SegmentedCache cache;

    //WARNING mapped name is producer specified.
    //For Jboss SpyMessages use simple "ConnectionFactory"
    @Resource(mappedName="jms/ConnectionFactory")
    private ConnectionFactory connectionFactory;

    @Resource(mappedName=SampleGeoInfoRequester.QUEUE_NAME)
    private Queue queue;

    private void fillMessage(BytesMessage msg, Long connectionId, String providerName, String versionApi, GeographicCoordinates fromSite, GeographicCoordinates toSite) throws JMSException {
        msg.setLongProperty(SampleGeoInfoRequester.CONNECTION_ID, connectionId);
        msg.setStringProperty(SampleGeoInfoRequester.PROVIDER_NAME, providerName);
        msg.setStringProperty(SampleGeoInfoRequester.VERSION_API, versionApi);
        msg.writeFloat((float) fromSite.getLatitude());
        msg.writeFloat((float) toSite.getLatitude());
        msg.writeFloat((float) fromSite.getLongitude());
        msg.writeFloat((float) toSite.getLongitude());
    }

    public ResponseGeoInfo incacheFastestRouteRequest(Long clientId, GeographicCoordinates fromSite, GeographicCoordinates toSite) {
        Pair<String, String> providerKey = providers.getProviderKey(clientId);
        GeoProviderSettings settings = new GeoProviderSettings(providerKey.getFirst(), providerKey.getSecond(), null);
        RoutesCache routes = cache.getSegment(settings);
        Pair<Double, Long> leg = routes.get(fromSite, toSite);
        if (leg != null) {
            GeoInfoRequestId requestKey =
                    new GeoInfoRequestId(providerKey.getFirst(), providerKey.getSecond(), GeoInfoRequestType.FASTEST_ROUTE, fromSite, toSite);
            if (containsError(leg)) {
                return new ResponseRoutingError(requestKey, leg.getFirst(), leg.getSecond(), null, null);
            }
            return new ResponseRouting(requestKey, leg.getFirst(), leg.getSecond(), null);
        }
        return null;
    }

    private boolean containsError(Pair<Double, Long> leg) {
        return leg.getFirst() == null || leg.getFirst() <= 0 || leg.getSecond() == null || leg.getSecond() <= 0;
    }

    public ResponseGeoInfo fastestRouteRequest(Long clientId, GeographicCoordinates fromSite, GeographicCoordinates toSite) throws JMSException {
        Connection connection = connectionFactory.createConnection();
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        MessageProducer messageProducer = session.createProducer(queue);
        BytesMessage msg = session.createBytesMessage();
        Pair<String, String> providerKey = providers.getProviderKey(clientId);
        fillMessage(msg, clientId, providerKey.getFirst(), providerKey.getSecond(), fromSite, toSite);
        messageProducer.send(msg);

        return new SenderResponce(providerKey.getFirst(), providerKey.getSecond(), GeoInfoRequestType.FASTEST_ROUTE, fromSite, toSite);
    }

    public boolean isRequestComplete(GeoInfoRequestId requestId) {
        throw new UnsupportedOperationException("Method isRequestComplete of class com.magenta.maxoptra.scheduler.api.TssGeoInfoProvider is unimplemented!");
    }

    private class SenderResponce extends ResponseGeoInfo {

        static final long serialVersionUID = -8639708546656040842L;

        private final GeoInfoRequestId requestId;

        public SenderResponce(String providerName, String versionApi, GeoInfoRequestType fastestRoute, GeographicCoordinates fromSite, GeographicCoordinates toSite) {
            this.requestId = new GeoInfoRequestId(providerName, versionApi, fastestRoute, fromSite, toSite);
        }

        @Override
        public GeoInfoRequestId getRequestId() {
            return requestId;
        }

        @Override
        public Long getPlacedTime() {
            return null;
        }
    }
}
